﻿using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Media;

using Xceed.Document.NET;
using Xceed.Words.NET;

using DrawingColor = System.Drawing.Color;

namespace FireCounter;

public partial class MainWindow : Window
{
    private static readonly SolidColorBrush _errorBrush = new(Colors.Red);

    private static readonly SolidColorBrush _normalBrush = new(Colors.Black);

    private static readonly string _sep = new('=', 25);

    private readonly List<string> _emptyItems = [];

    private readonly List<string> _nonstandardItems = [];

    private readonly Dictionary<string, Result> _results = [];

    private string _filePath = null!;

    public MainWindow()
    {
        InitializeComponent();

        var ver = Assembly.GetExecutingAssembly().GetName().Version;
        Title += $" v{ver?.Major}.{ver?.Minor}";
    }

    private async void BtnCount_ClickAsync(object sender, RoutedEventArgs e)
    {
        try
        {
            pbBusy.Visibility = Visibility.Visible;

            tbResult.Text = "";

            await Task.Run(() => {
                using var doc = LoadFile();

                if (doc is null)
                {
                    return;
                }

                var table = Check(doc);

                if (table is null)
                {
                    return;
                }

                Count(doc);

                Dispatcher.Invoke(PrintResult);

                Write(doc, table);
            });
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                this,
                ex.Message,
                "发生错误",
                MessageBoxButton.OK,
                MessageBoxImage.Error);
        }
        finally
        {
            pbBusy.Visibility = Visibility.Collapsed;
        }
    }

    private void CenterWindowOnScreen()
    {
        var workArea = SystemParameters.WorkArea;
        //Left = ((workArea.Width - Width) / 2) + workArea.Left;
        Top = ((workArea.Height - Height) / 2) + workArea.Top;
    }

    private Table? Check(DocX doc)
    {
        var table = doc.Tables.FirstOrDefault(x => x.Rows?.FirstOrDefault()?.Cells.Count == 4
            && x.Rows.FirstOrDefault()?.Cells.ElementAtOrDefault(2)?.Paragraphs.FirstOrDefault()?.Text == "一般项目数量");

        if (table is null)
        {
            Dispatcher.Invoke(() => MessageBox.Show(
                this,
                "未找到「本工程一般项目统计表」",
                "错误",
                MessageBoxButton.OK,
                MessageBoxImage.Error));

            return null;
        }

        return table;
    }

    private void Count(DocX doc)
    {
        _results.Clear();
        _emptyItems.Clear();
        _nonstandardItems.Clear();

        var tables = doc.Tables;

        for (int i = 0; i < tables.Count; i++)
        {
            if (tables[i].Rows.ElementAtOrDefault(1)?.Cells.Count != 6)
            {
                continue;
            }

            string itemName = "???";
            string subItemName = "???";

            for (int r = 0; r < tables[i].RowCount; r++)
            {
                var row = tables[i].Rows[r];

                if (row.Cells.Count != 6)
                {
                    continue;
                }

                string c3 = row.Cells[2].GetPlainText();

                if (c3 is not ("主控项目" or "一般项目"))
                {
                    continue;
                }

                string c1 = row.Cells[0].GetPlainText();

                if (!String.IsNullOrWhiteSpace(c1))
                {
                    itemName = c1;
                }

                string c2 = row.Cells[1].GetPlainText();

                if (!String.IsNullOrWhiteSpace(c2))
                {
                    subItemName = c2;
                }

                if (!_results.TryGetValue(itemName, out var result))
                {
                    result = new Result();
                    _results.Add(itemName, result);
                }

                var cell6 = row.Cells[5];
                cell6.Trim();
                cell6.Center();

                string c6 = cell6.GetPlainText();

                if (String.IsNullOrWhiteSpace(c6))
                {
                    _emptyItems.Add($"{itemName} / {subItemName}");
                    cell6.FillColor = DrawingColor.Yellow;
                }
                else if (c6 is not ("符合要求" or "不符合要求" or "原主体已验收" or "不涉及"))
                {
                    _nonstandardItems.Add($"{itemName} / {subItemName}");
                    cell6.FillColor = DrawingColor.Yellow;
                }
                else
                {
                    cell6.FillColor = DrawingColor.Transparent;
                }

                if (c3 == "一般项目")
                {
                    if (!String.IsNullOrWhiteSpace(c6) && c6 != "不涉及")
                    {
                        result.InvolvedCount++;
                    }

                    if (c6 == "不符合要求")
                    {
                        result.FailCount++;
                    }
                }
            }
        }
    }

    private DocX? LoadFile()
    {
        try
        {
            return DocX.Load(_filePath);
        }
        catch (IOException)
        {
            Dispatcher.Invoke(() => MessageBox.Show(
                this,
                "文件被占用，请关闭文件后重试。",
                "错误",
                MessageBoxButton.OK,
                MessageBoxImage.Error));

            return null;
        }
    }

    private void PrintResult()
    {
        if (_emptyItems.Count > 0)
        {
            string emptyItems = String.Join("\n", _emptyItems);
            tbResult.Text += $"⚠️以下项目未填写 [检测项目判定]：\n{emptyItems}\n{_sep}\n\n";
        }

        if (_nonstandardItems.Count > 0)
        {
            string nonstandardItems = String.Join("\n", _nonstandardItems);
            tbResult.Text += $"⚠️以下项目 [检测项目判定] 不规范：\n{nonstandardItems}\n{_sep}\n\n";
        }

        string results = String.Join("\n", _results.Select(x => $"{x.Key}: {x.Value}"));
        tbResult.Text += $"🔢统计结果：\n{results}";
    }

    private void TextBox_PreviewDragOver(object sender, DragEventArgs e)
    {
        e.Handled = true;
    }

    private void Window_DragEnter(object sender, DragEventArgs e)
    {
        e.Effects = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Link : DragDropEffects.None;
    }

    private void Window_Drop(object sender, DragEventArgs e)
    {
        tbResult.Text = "";

        string? path;

        try
        {
            path = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0)?.ToString();
        }
        catch
        {
            return;
        }

        _filePath = path!;
        tbFilePath.Text = path;

        string? ext = Path.GetExtension(path);

        if (ext != ".docx")
        {
            btnCount.IsEnabled = false;
            root.ToolTip = $"{ext} 不是有效的文档格式";
            tbFilePath.Foreground = _errorBrush;

            MessageBox.Show(
                this,
                $"{ext} 不是有效的文档格式。\n\n" +
                "仅支持 .docx 文档！",
                "格式错误",
                MessageBoxButton.OK,
                MessageBoxImage.Error);

            return;
        }

        tbFilePath.Foreground = _normalBrush;
        btnCount.IsEnabled = true;
        root.ToolTip = null;
    }

    private async void Window_SizeChangedAsync(object sender, SizeChangedEventArgs e)
    {
        await Task.Delay(1);
        CenterWindowOnScreen();
    }

    private void Write(DocX doc, Table table)
    {
        foreach (var row in table.Rows[1..^1])
        {
            row.Cells[2].FillColor = DrawingColor.Yellow;
            row.Cells[3].FillColor = DrawingColor.Yellow;
        }

        var list = new List<(string, int)>();

        foreach (var row in table.Rows[..^1].Index())
        {
            list.Add((row.Item.Cells[1].GetPlainText(), row.Index));
        }

        list.RemoveAt(0);

        var indexedResults = new Dictionary<int, (string, Result)>();
        var lostItems = new List<string>();

        foreach (var (key, id) in list)
        {
            if (_results.TryGetValue(key, out var result))
            {
                indexedResults[id] = (key, result);
            }
            else
            {
                lostItems.Add(key);
            }
        }

        foreach ((int idx, (string itemName, var result)) in indexedResults)
        {
            var cell3 = table.Rows[idx].Cells[2];
            cell3.Clear();
            var p3 = cell3.InsertParagraph(result.InvolvedCount.ToString(), false, CellEx.Formatting);
            cell3.Center();
            cell3.FillColor = DrawingColor.Transparent;

            var cell4 = table.Rows[idx].Cells[3];
            cell4.Clear();
            var p4 = cell4.InsertParagraph(result.FailCount.ToString(), false, CellEx.Formatting);
            cell4.Center();
            cell4.FillColor = DrawingColor.Transparent;
        }

        doc.Save();

        Dispatcher.Invoke(() => {
            string lostItemsTip = lostItems.Count > 0 ? $"* 以下项目未写入成功：\n{String.Join("\n", lostItems)}" : "";
            string emptyTip = _emptyItems.Count > 0 ? $"* 存在 {_emptyItems.Count} 个未填写的 [检测项目判定] 项目" : "";
            string nonstandardTip = _nonstandardItems.Count > 0 ? $"* 存在 {_nonstandardItems.Count} 个填写不规范的 [检测项目判定] 项目" : "";
            string tips = $"{lostItemsTip}\n\n{emptyTip}\n{nonstandardTip}".Trim();
            bool hasTip = !String.IsNullOrEmpty(tips);

            MessageBox.Show(
                this,
                $"统计结果已写入到文档 -> 「本工程一般项目统计表」。\n\n{tips}".Trim(),
                "统计完成",
                MessageBoxButton.OK,
                hasTip ? MessageBoxImage.Warning : MessageBoxImage.Information);
        });
    }
}
